home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / BEERSRC.ZIP / EDIT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-27  |  33.2 KB  |  1,598 lines

  1.  
  2. #define MAIN_MODULE
  3.  
  4. #pragma hdrfile "edit.sym"
  5.  
  6. #include <stdio.h>
  7. #include <io.h>
  8. #include <sys\stat.h>
  9. #include <stdlib.h>
  10. #include <dos.h>
  11. #include <fcntl.h>
  12. #include <alloc.h>
  13. #include <string.h>
  14. #include <stdarg.h>
  15. #include <conio.h>
  16.  
  17. #pragma hdrstop
  18.  
  19. #include "mouse.h"
  20. #include "sound.h"
  21. #include "baller.h"
  22. #include "xmode.h"
  23.  
  24.  
  25. #define   STATLINE              212
  26.  
  27.  
  28.  
  29. void plot(int x, int y, int c);
  30.  
  31.  
  32. // Globale wurschtli variablen.
  33.  
  34.  
  35. int getkey(void);
  36.  
  37.  
  38. int    nsprites;
  39. struct sTableEntry *sprite = NULL;
  40. int    sspr;                // Selected sprite;
  41.  
  42.  
  43. int    speed = 4;
  44.  
  45.  
  46. struct sprstrc *font;
  47.  
  48.  
  49. int    pathedit = 0;
  50. int    attackedit = 0;
  51.  
  52.  
  53. int    x, y, b, x0, y0;
  54. int    path;
  55. int    handle;
  56. int    handle2;
  57. int    pixelcount;
  58. int    xa, ya;
  59.  
  60. int    lastkey;
  61.  
  62. int    tmpxstart, tmpystart;
  63. struct foestrc  tmpfoe; // ____\
  64. int    tmp[3000];    //     / This two lines mustn't be cut.
  65. int    tmppos;
  66. int    runpos;
  67. int    runx, runy;
  68.  
  69. int    nfoes = 0;
  70. int    xstart[400], ystart[400];
  71. int    pathlen[400];
  72. struct foestrc *foe[400];
  73. int    sfoe = -1;
  74. //---------
  75. unsigned count = 0;
  76. int    nattacks = 0;
  77. #define MAXATT 400
  78. struct attackstrc attack[MAXATT];
  79. int    sattack = -1;
  80. struct pathstrc {
  81.    int   foe;        // Number.
  82.    int   x, y;        // Position of foe.
  83.    int   pos;        // Positon in path.
  84.    int   savepos;
  85.    int   savex, savey;
  86.    int   sprite;    // Current sprite.
  87. };
  88. #define MAXANI 200
  89. struct pathstrc animate[MAXANI];
  90.  
  91.  
  92. //---------------------------------------------
  93.  
  94. void initanimate(void)
  95. {
  96.    int  i;
  97.  
  98.    for (i = 0; i < MAXANI; i++) animate[i].foe = -1;
  99.  
  100. }
  101.  
  102.  
  103. void xorline(int x1, int y1, int x2, int y2, int c)
  104. {
  105.  
  106.    int   x, y, z, dx, dy, dz, i1, i2;
  107.  
  108.  
  109.    dx = abs(x1 - x2); dy = abs(y1 - y2);
  110.    if (x1 < x2) {
  111.       x = x1; y = y1;
  112.       if (y1 > y2) z = -1; else z = 1;
  113.    } else {
  114.       x = x2; y = y2;
  115.       if (y2 > y1) z = -1; else z = 1;
  116.    }
  117.  
  118.    if (dx > dy) i2 = dx; else i2 = dy;
  119.    dz = i2 >> 1;
  120.    plot(x, y, getpixel(x, y) ^ c);
  121.    for (i1 = 1; i1 <= i2; i1++) {
  122.       if (dz < dx) {
  123.      dz = dz + dy; x++;
  124.       }
  125.       if (dz >= dx) {
  126.      dz = dz - dx; y += z;
  127.       }
  128.       plot(x, y, getpixel(x, y) ^ c);
  129.    }
  130.  
  131. }
  132.  
  133. void line(int x1, int y1, int x2, int y2, int c)
  134. {
  135.  
  136.    int   x, y, z, dx, dy, dz, i1, i2;
  137.  
  138.  
  139.    dx = abs(x1 - x2); dy = abs(y1 - y2);
  140.    if (x1 < x2) {
  141.       x = x1; y = y1;
  142.       if (y1 > y2) z = -1; else z = 1;
  143.    } else {
  144.       x = x2; y = y2;
  145.       if (y2 > y1) z = -1; else z = 1;
  146.    }
  147.  
  148.    if (dx > dy) i2 = dx; else i2 = dy;
  149.    dz = i2 >> 1;
  150.    plot(x, y, c);
  151.    for (i1 = 1; i1 <= i2; i1++) {
  152.       if (dz < dx) {
  153.      dz = dz + dy; x++;
  154.       }
  155.       if (dz >= dx) {
  156.      dz = dz - dx; y += z;
  157.       }
  158.       plot(x, y, c);
  159.    }
  160.  
  161. }
  162.  
  163. void tmpline(int x1, int y1, int x2, int y2, int speed, int ignore)
  164. {
  165.    int  x, y, z0, z1, dx, dy, dz, i1, i2;
  166.  
  167.    dx = abs(x1-x2); dy = abs(y1-y2);
  168.    if (x1 < x2) z0 = 1; else z0 = -1;
  169.    if (y1 < y2) z1 = 1; else z1 = -1;
  170.    x = x1; y = y1;
  171.    if (dx > dy) i2 = dx; else i2 = dy;
  172.    dz = i2/2;
  173.    if (((pixelcount % speed) == 0) && !ignore) {
  174.       tmp[tmppos++] = x - runx; tmp[tmppos++] = y - runy;
  175.       runx = x; runy = y;
  176.    }
  177.    pixelcount++;
  178.    for (i1 = 1; i1 < i2; i1++) {
  179.       if (dz < dx)  { dz += dy; x += z0; }
  180.       if (dz >= dx) { dz -= dx; y += z1; }
  181.       if ((pixelcount % speed) == 0) {
  182.      tmp[tmppos++] = x - runx; tmp[tmppos++] = y - runy;
  183.      runx = x; runy = y;
  184.       }
  185.       pixelcount++;
  186.    }
  187. }
  188.  
  189. int getdec(char *text)
  190. {
  191.    int   i;
  192.    int   ch;
  193.    char  str[40];
  194.    int   pos;
  195.  
  196.    clearregion(STATLINE-8, 8);
  197.    writetext(0, STATLINE-8, text, font);
  198.  
  199.    i = 0;
  200.    pos = strlen(text)*8 + 8;
  201.    while ((ch = getch()) != 13) {
  202.       if (ch == 8) {
  203.      if (i > 0) {
  204.      pos -= 8; putspritedirect(font, pos, STATLINE-8, 0);
  205.      i--;
  206.      }
  207.       } else {
  208.      str[i++] = ch;
  209.      putspritedirect(font, pos, STATLINE-8, ch - ' ');
  210.      pos+=8;
  211.       }
  212.  
  213.    }
  214.    str[i] = 0;
  215.  
  216.    return atoi(str);
  217.  
  218. }
  219.  
  220.  
  221. #pragma argsused
  222. void error(char *s, int code, ...)
  223. {
  224.    writetext(0, 0, s, font);
  225.    getch();
  226.    writetext(0,0,"                                   ", font);
  227.  
  228. }
  229.  
  230.  
  231. int findcommand(void *path, int i, int dir)
  232. {
  233.    unsigned *data;
  234.  
  235.    if (path == NULL) data = (unsigned *)tmp;
  236.    else data = (unsigned *)path;
  237.  
  238.    if (i < 0) return i+dir;
  239.    if (dir == -1) {
  240.       if (i == 0) return -1;
  241.       i--;
  242.       if ((data[i] == FOEENDPATH) || (data[i] == FOECYCLEPATH)) return i;
  243.       if ((i >= 3) && (data[i-3] == FOERELEASEFOE)) return i-3;
  244.       if (data[i] == FOEMARK) return i;
  245.       return i-1;
  246.    } else {
  247.       if ((data[i] == FOEENDPATH) || (data[i] == FOECYCLEPATH)) return i+1;
  248.       if (data[i] == FOERELEASEFOE) return i+4;
  249.       if (data[i] == FOEMARK) return i+1;
  250.       return i+2;
  251.    }
  252.  
  253. }
  254.  
  255.  
  256. int dispatch(int pos, char *s)
  257. {
  258.  
  259.    if (pos < 0) {
  260.       strcpy(s, "NONE");
  261.       return pos+1;
  262.    }
  263.    switch (tmp[pos]) {
  264.       case FOEENDPATH:
  265.      strcpy(s, "END");
  266.      pos++;
  267.      break;
  268.       case FOECYCLEPATH:
  269.      strcpy(s, "CYCLE");
  270.      pos++;
  271.      break;
  272.       case FOEMARK:
  273.      strcpy(s, "MARK");
  274.      pos++;
  275.      break;
  276.       case FOECHANGESPRITE:
  277.      sprintf(s, "C-SPRITE %02d", tmp[pos+1]);
  278.      pos += 2;
  279.      break;
  280.       case FOERELEASEFOE:
  281.      sprintf(s, "RELEASE %02d", tmp[pos+1]);
  282.      pos += 4;
  283.      break;
  284.       case FOESOUND:
  285.      sprintf(s, "SOUND %02d", tmp[pos+1]);
  286.      pos += 2;
  287.      break;
  288.       default:
  289.      sprintf(s, "%03d,%03d", tmp[pos], tmp[pos+1]);
  290.      pos += 2;
  291.      break;
  292.    }
  293.  
  294.    return pos;
  295. }
  296.  
  297. void dispatchattack(int n, char *s)
  298. {
  299.    switch (attack[n].foe) {
  300.       case A_GOFIELD:
  301.      sprintf(s, "%X GOSTARFIELD", attack[n].count);
  302.      break;
  303.       case A_STOPFIELD:
  304.      sprintf(s, "%X STOPFIELD", attack[n].count);
  305.      break;
  306.       case A_SOUND:
  307.      sprintf(s, "%X SOUND %d", attack[n].count, attack[n].x);
  308.      break;
  309.       case A_MARK:
  310.      sprintf(s, "%X MARK", attack[n].count);
  311.      break;
  312.       default:
  313.      sprintf(s, "%X FOE %d", attack[n].count, attack[n].foe);
  314.      break;
  315.    }
  316. }
  317.  
  318. void status(void)
  319. {
  320.    char   text[80];
  321.    char   comm[80];
  322.    int    last;
  323.  
  324.  
  325.    if (!attackedit) {
  326.       sprintf(text, "SH.%-3d SC.%-5u EX.%-2d SP.%-2d MEM.%6lu",
  327.        tmpfoe.shield, tmpfoe.score, tmpfoe.expl, speed, coreleft());
  328.       writetext(0, STATLINE, text, font);
  329.  
  330.       if (sfoe != -1) {
  331.      text[0] = 0;    // Clear text.
  332.      last = findcommand(NULL, runpos, -1);
  333.      last = dispatch(last, comm);
  334.      strcat(text, comm); strcat(text, "  ");
  335.      last = dispatch(last, comm);
  336.      strcat(text, comm); strcat(text, "  ");
  337.      dispatch(last, comm);
  338.      strcat(text, comm); strcat(text, "        ");
  339.      writetext(0, STATLINE-8, text, font);
  340.  
  341.      sprintf(text, "FOE %d", sfoe);
  342.      writetext(0, 0, text, font);
  343.  
  344.       }
  345.       writetext(284, STATLINE-8, "    ", font);
  346.  
  347.    } else {
  348.       clearregion(STATLINE-8, 16);
  349.       sprintf(text, "%04X", count);
  350.       writetext(284, STATLINE, text, font);
  351.       if (sattack != -1) {
  352.      dispatchattack(sattack, text);
  353.      writetext(0, STATLINE, text, font);
  354.       }
  355.    }
  356.  
  357.  
  358. }
  359.  
  360.  
  361.  
  362. void editvalues(void)
  363. {
  364.    char   text[80];
  365.  
  366.    printf("%xh=ENDLEVEL, %xh=INVINCIBLE, %xh=TRANSPARENT, %xh=STOPCOUNT\n",
  367.       FOE_ENDLEVEL, FOE_INVINCIBLE, FOE_TRANSPARENT, FOE_STOPCOUNT);
  368.    printf("%xh=PATH, %xh=LINE\n", FOE_PATH, FOE_LINE);
  369.    printf("Flags [%xh]: ", tmpfoe.flags);
  370.    fflush(stdin);
  371.    gets(text);
  372.    if (strlen(text) != 0) sscanf(text, "%x", &tmpfoe.flags);
  373.  
  374.    printf("Shield [%d]: ", tmpfoe.shield);
  375.    fflush(stdin);
  376.    gets(text);
  377.    if (strlen(text) != 0) sscanf(text, "%d", &tmpfoe.shield);
  378.  
  379.    printf("Score [%u]: ", tmpfoe.score);
  380.    fflush(stdin);
  381.    gets(text);
  382.    if (strlen(text) != 0) sscanf(text, "%d", &tmpfoe.score);
  383.  
  384.    printf("Explosion [%d]: ", tmpfoe.expl);
  385.    fflush(stdin);
  386.    gets(text);
  387.    if (strlen(text) != 0) sscanf(text, "%d", &tmpfoe.expl);
  388.  
  389.    printf("Speed [%d]: ", tmpfoe.speed);
  390.    fflush(stdin);
  391.    gets(text);
  392.    if (strlen(text) != 0) sscanf(text, "%d", &tmpfoe.speed);
  393.  
  394.    if (sfoe != -1) {
  395.       *foe[sfoe] = tmpfoe;
  396.    }
  397.  
  398. }
  399.  
  400. void storepath(void)
  401. {
  402.  
  403.    if ((foe[nfoes] = malloc(sizeof(struct foestrc)+tmppos*2)) != NULL) {
  404.       sfoe = nfoes++;
  405.       handle2 = defsprite(sprite[tmpfoe.sprite].sprite, sprite[tmpfoe.sprite].flags);
  406.       xstart[sfoe] = tmpxstart; ystart[sfoe] = tmpystart;
  407.       pathlen[sfoe] = sizeof(struct foestrc) + tmppos*2;
  408.       *foe[sfoe] = tmpfoe;
  409.       memcpy(&foe[sfoe]->path, tmp, tmppos*2);
  410.    } else
  411.       error("OUT OF MEMORY IN STOREPATH", 0);
  412.  
  413. }
  414.  
  415.  
  416. void delpath(void)
  417. {
  418.    int      i;
  419.    int      pos;
  420.    unsigned *data;
  421.  
  422.    if (sfoe != -1) {
  423.       free(foe[sfoe]);
  424.       for (i = sfoe + 1; i < nfoes; i++) {
  425.      foe[i-1] = foe[i];
  426.      xstart[i-1] = xstart[i];
  427.      ystart[i-1] = ystart[i];
  428.      pathlen[i-1] = pathlen[i];
  429.       }
  430.       nfoes--;
  431. // Adjust references to other foes.
  432.       for (i = 0; i < nfoes; i++) {
  433.      pos = 0; data = (unsigned *) &foe[i]->path;
  434.      while (data[pos] != FOEENDPATH && data[pos] != FOECYCLEPATH) {
  435.         if (data[pos] == FOERELEASEFOE) {
  436.            if (data[pos+1] > sfoe) data[pos+1]--;
  437.         }
  438.         pos = findcommand(data, pos, 1);
  439.      }
  440.       }
  441.       for (i = 0; i < nattacks; i++) {
  442.      if (attack[i].foe > sfoe) attack[i].foe--;
  443.       }
  444.       if (nfoes == 0) sfoe = -1;
  445.       else {
  446.      sfoe--; if (sfoe < 0) sfoe = nfoes - 1;
  447.       }
  448.    }
  449. }
  450.  
  451.  
  452. void delattack(void)
  453. {
  454.    int i;
  455.    if (sattack != -1) {
  456.       for (i = sattack + 1; i < nattacks; i++)
  457.      attack[i-1] = attack[i];
  458.       nattacks--;
  459.       if (nattacks == 0) sattack = -1;
  460.       else {
  461.      sattack--; if (sattack < 0) sattack = 0;
  462.       }
  463.    }
  464. }
  465.  
  466. void showpath(int x, int y, int path, int c)
  467. {
  468.    int  i;
  469.    int  c1, c2;
  470.  
  471.    i = 0;
  472.    x += sprite[foe[path]->sprite].sprite->xs/2;
  473.    y += sprite[foe[path]->sprite].sprite->ys/2;
  474.    plot(x, y, c);
  475.    c1 = foe[path]->path[i]; c2 = foe[path]->path[i+1];
  476.    while (((unsigned)c1 != FOEENDPATH) && ((unsigned)c1 != FOECYCLEPATH)) {
  477.  
  478.       switch (c1) {
  479.      case FOEMARK:
  480.         plot(x, y, 12);
  481.         i += 1;
  482.         break;
  483.      case FOECHANGESPRITE:
  484.      case FOESOUND:
  485.         i += 2;
  486.         break;
  487.      case FOERELEASEFOE:
  488.         showpath(x+foe[path]->path[i+2], y+foe[path]->path[i+3], c2, (c == 0) ? 0 : c+1);
  489.         i += 4;
  490.         break;
  491.  
  492.      default:
  493.         plot(x+=c1, y+=c2, c);
  494.         i += 2;
  495.         break;
  496.  
  497.       }
  498.       c1 = foe[path]->path[i]; c2 = foe[path]->path[i+1];
  499.    }
  500.  
  501. }
  502.  
  503.  
  504.  
  505. void newfoe(void)
  506. {
  507.  
  508.    clearscreen();
  509.    status();
  510.  
  511.    if (sfoe != -1) {
  512.       tmpfoe = *foe[sfoe];
  513.       tmpxstart = xstart[sfoe]; tmpystart = ystart[sfoe];
  514.  
  515.       killsprite(handle2);
  516.       handle2 = defsprite(sprite[tmpfoe.sprite].sprite, sprite[tmpfoe.sprite].flags);
  517.       runpos = -1; runx = tmpxstart; runy = tmpystart;
  518.       lastkey = 'M';
  519.       putsprite(handle2, runx, runy, 0);
  520.  
  521.       showpath(runx, runy, sfoe, 11);
  522.       tmppos = pathlen[sfoe]-sizeof(struct foestrc);
  523.       memcpy(tmp, &foe[sfoe]->path, tmppos);
  524.       tmppos = tmppos/2 + 1;
  525.    }
  526.  
  527. }
  528.  
  529. void newsprite(void)
  530. {
  531.    killsprite(handle);
  532.    handle = defsprite(sprite[sspr].sprite, sprite[sspr].flags);
  533.    setborder(-sprite[sspr].sprite->xs, -sprite[sspr].sprite->ys, 320, YMAX);
  534.    xa = sprite[sspr].sprite->xs/2; ya = sprite[sspr].sprite->ys/2;
  535.    setpos(x-xa, y-ya);
  536.    getpos(&b, &x, &y);
  537.    putsprite(handle, x, y, 0);
  538.  
  539. }
  540.  
  541. int sort_cmp(const void *ptr1, const void *ptr2)
  542. {
  543.    struct attackstrc *a1, *a2;
  544.  
  545.    a1 = (struct attackstrc *) ptr1;
  546.    a2 = (struct attackstrc *) ptr2;
  547.    return(a1->count - a2->count);
  548.  
  549. }
  550.  
  551. void sort(void)
  552. {
  553.  
  554.    qsort(attack, nattacks, sizeof(struct attackstrc), sort_cmp);
  555.  
  556. }
  557.  
  558.  
  559. void defpath(int f, int x, int y)
  560. {
  561.    int  i;
  562.  
  563.    for (i = 0; i < MAXANI; i++)
  564.       if (animate[i].foe == -1) {
  565.      animate[i].foe = f;
  566.      animate[i].x = x;
  567.      animate[i].y = y;
  568.      animate[i].pos = 0;
  569.      animate[i].sprite = defsprite(sprite[foe[f]->sprite].sprite,
  570.                        sprite[foe[f]->sprite].flags);
  571.      break;
  572.       }
  573.  
  574. }
  575.  
  576. void expath(struct pathstrc *lall, int dir, int show)
  577. {
  578.    int  pos;
  579.    int  *data;
  580.  
  581.    pos = lall->pos;
  582.    data = foe[lall->foe]->path;
  583.  
  584.  
  585.    do {
  586.    if (pos < 0) {
  587.       lall->foe = -1;
  588.       killsprite(lall->sprite);
  589.       return;
  590.    }
  591.  
  592.    switch (data[pos]) {
  593.       case FOEENDPATH:
  594.      lall->foe = -1;
  595.      killsprite(lall->sprite);
  596.      return;
  597.       case FOECYCLEPATH:
  598.      lall->pos = pos = lall->savepos;
  599.      lall->x = lall->savex; lall->y = lall->savey;
  600.      break;
  601.       case FOEMARK:
  602.      lall->savepos = pos;
  603.      lall->savex = lall->x;
  604.      lall->savey = lall->y;
  605.      break;
  606.       case FOECHANGESPRITE:
  607.      killsprite(lall->sprite);
  608.      lall->sprite = defsprite(sprite[data[pos+1]].sprite, sprite[data[pos+1]].flags);
  609.      break;
  610.       case FOERELEASEFOE:
  611.      defpath(data[pos+1], data[pos+2]+lall->x, data[pos+3]+lall->y);
  612.      break;
  613.       case FOESOUND:
  614.      break;
  615.       default:
  616.      if (dir == 1) {
  617.         lall->x += data[pos]; lall->y += data[pos+1];
  618.      } else {
  619.         lall->x -= data[pos]; lall->y -= data[pos+1];
  620.      }
  621.      if (show) putsprite(lall->sprite, lall->x, lall->y, 0);
  622.      lall->pos = pos = findcommand(data, pos, dir);
  623.      return;
  624.    }
  625.    lall->pos = pos = findcommand(data, pos, dir);
  626.    } while (1);
  627.  
  628. }
  629.  
  630.  
  631. void animateonestep(int dir, int show)
  632. {
  633.    int   i;
  634.  
  635.    if (count != 0xffff && nattacks > 0) {
  636.    for (i = 0; i < MAXATT; i++) {
  637.       if ((attack[i].count == count) && !(attack[i].foe & 0x8000))
  638.      defpath(attack[i].foe, attack[i].x, attack[i].y);
  639.    }
  640.    }
  641.    for (i = 0; i < MAXANI; i++) {
  642.       if (animate[i].foe != -1) expath(&animate[i], dir, show);
  643.    }
  644.  
  645. }
  646.  
  647. void animateabit(int ch)
  648. {
  649.    int  i;
  650.  
  651.    switch (ch) {
  652.      case 'H': // Cursor Up
  653.            sattack++; if (sattack >= nattacks) sattack = nattacks-1;
  654.            killallsprites();
  655.            initanimate();
  656.            clearscreen();
  657.            if (sattack != -1) {
  658.               count = attack[sattack].count-1;
  659.               showpath(attack[sattack].x, attack[sattack].y, attack[sattack].foe, 14);
  660.            }
  661.            break;
  662.      case 'P': // Cursor Down
  663.            if (sattack > 0) sattack--;
  664.            killallsprites();
  665.            initanimate();
  666.            clearscreen();
  667.            if (sattack != -1) {
  668.               count = attack[sattack].count-1;
  669.               showpath(attack[sattack].x, attack[sattack].y, attack[sattack].foe, 14);
  670.            }
  671.            break;
  672.      case 'M': count++;  // Cursor right
  673.            animateonestep(1, TRUE);
  674.            break;
  675.      case 'K': --count;  // cursor left
  676.            killallsprites();
  677.            initanimate();
  678.            break;
  679.  
  680.      case '6': for (i = 0; i < 15; i++) {
  681.               count++;
  682.               animateonestep(1, FALSE);
  683.            }
  684.            count++; animateonestep(1, TRUE);
  685.            break;
  686.      case '4': count -= 16;  // Fast left
  687.            killallsprites();
  688.            initanimate();
  689.            break;
  690.    }
  691.  
  692.  
  693. }
  694.  
  695.  
  696. int excommand(int pos, int dir)
  697. {
  698.  
  699.    if ((pos < 0) && (dir == -1)) return pos;
  700.    if (((unsigned)tmp[pos] == FOEENDPATH) && (dir == 1)) return pos;
  701.    if (((unsigned)tmp[pos] == FOECYCLEPATH) && (dir == 1)) return pos;
  702.  
  703.    if ((pos = findcommand(NULL, pos, dir)) >= 0) {
  704.  
  705.       switch (tmp[pos]) {
  706.      case FOEENDPATH:
  707.         break;
  708.      case FOECYCLEPATH:
  709.         break;
  710.      case FOEMARK:
  711.         break;
  712.      case FOECHANGESPRITE:
  713.         killsprite(handle2);
  714.         handle2 = defsprite(sprite[tmp[pos+1]].sprite,sprite[tmp[pos+1]].flags);
  715.         break;
  716.      case FOERELEASEFOE:
  717.      case FOESOUND:
  718.         break;
  719.      default:
  720.         removesprite(handle2, runx, runy);
  721.         if (dir == 1)
  722.            putsprite(handle2, runx+=tmp[pos], runy+=tmp[pos+1], 0);
  723.         else
  724.            putsprite(handle2, runx-=tmp[pos], runy-=tmp[pos+1], 0);
  725.         break;
  726.       }
  727.    }
  728.    return pos;
  729. }
  730.  
  731.  
  732. int roll(int n, int lb, int ub, int dir)
  733. {
  734.    if (dir == 1) {
  735.       n++; if (n > ub) n = lb;
  736.    } else {
  737.       n--; if (n < lb) n = ub;
  738.    }
  739.  
  740.    return n;
  741. }
  742.  
  743.  
  744. void refreshpath(void)
  745. {
  746.    free(foe[sfoe]);
  747.  
  748.    if ((foe[sfoe] = malloc(sizeof(struct foestrc)+tmppos*2)) != NULL) {
  749.       *foe[sfoe] = tmpfoe;
  750.       memcpy(&foe[sfoe]->path, tmp, tmppos*2);
  751.    } else
  752.       error("CRITICAL OUT OF MEMORY. PATH LOST. EDITOR UNSTABLE. QUIT!!!",0);
  753. }
  754.  
  755. void deletecommand(int pos)
  756. {
  757.    int  i;
  758.  
  759.    if (runpos < 0) return;
  760.    memmove(&tmp[pos], &tmp[i = findcommand(NULL, pos, 1)], (tmppos-pos)*2);
  761.    i -= pos;
  762.    tmppos -= i;
  763.    refreshpath();
  764.  
  765. }
  766.  
  767. void insertcommand(int pos, int n, ...)
  768. {
  769.    va_list ap;
  770.    int     i;
  771.  
  772.    memmove(&tmp[pos+n], &tmp[pos], (tmppos-pos)*2);
  773.    tmppos += n;
  774.    pathlen[sfoe] += n*2;
  775.    va_start(ap, n);
  776.    for (i = 0; i < n; i++) {
  777.       tmp[pos+i] = va_arg(ap, int);
  778.    }
  779.    va_end(ap);
  780.  
  781.    refreshpath();
  782.  
  783. }
  784.  
  785.  
  786. void doonestep(int ch)
  787. {
  788.    int   i;
  789.  
  790.    switch (ch) {
  791.       case 'M': // Cursor Right
  792.         if (sfoe != -1) {
  793.            if (lastkey == 'M') {
  794.               runpos = excommand(runpos, 1);
  795.            } else {
  796.               lastkey = 'M';
  797.               runpos = findcommand(NULL, runpos, -1);
  798.               runpos = excommand(runpos, 1);
  799.            }
  800.  
  801.         }
  802.         break;
  803.       case 'K': // Cursor Left
  804.         if (sfoe != -1) {
  805.            if (lastkey == 'K') {
  806.               runpos = excommand(runpos, -1);
  807.            } else {
  808.               lastkey = 'K';
  809.               runpos = findcommand(NULL, runpos, 1);
  810.               runpos = excommand(runpos, -1);
  811.            }
  812.         }
  813.         break;
  814.  
  815.       case '4': // fast left
  816.         if (sfoe != -1) {
  817.            if (lastkey != 'K') {
  818.               lastkey = 'K';
  819.               runpos = findcommand(NULL, runpos, 1);
  820.            }
  821.            for (i = 0; i < 10; i++) {
  822.               runpos = excommand(runpos, -1);
  823.            }
  824.         }
  825.         break;
  826.       case '6': // fast right
  827.         if (sfoe != -1) {
  828.            if (lastkey != 'M') {
  829.               lastkey = 'M';
  830.               runpos = findcommand(NULL, runpos, -1);
  831.            }
  832.            for (i = 0; i < 10; i++) {
  833.               runpos = excommand(runpos, 1);
  834.            }
  835.         }
  836.         break;
  837.  
  838.    }
  839.  
  840. }
  841.  
  842.  
  843. int getpath(void)
  844. {
  845.    int   path0;
  846.    int   tmphandle;
  847.    int   quit;
  848.  
  849.    if ((tmphandle = defsprite(sprite[foe[path]->sprite].sprite,
  850.      sprite[foe[path]->sprite].flags)) == -1)
  851.       error("OUT OF MEM. SAVE YOUR WORK. CRASH IS NEAR.",0);
  852.    setborder(-sprite[foe[path]->sprite].sprite->xs, -sprite[foe[path]->sprite].sprite->ys, 320, YMAX);
  853.    showpath(x, y, path, 11);
  854.    putsprite(tmphandle, x, y, 0);
  855.    do {
  856.       x0 = x; y0 = y; path0 = path;
  857.       getpos(&b, &x, &y);
  858.       if (getkey()) return -1;
  859.       if ((x0 != x) || (y0 != y) || (path != path0)) {
  860.      showpath(x0, y0, path0, 0);
  861.      removesprite(tmphandle, x0, y0);
  862.      if (path != path0) {
  863.         killsprite(tmphandle);
  864.         if ((tmphandle = defsprite(sprite[foe[path]->sprite].sprite,
  865.           sprite[foe[path]->sprite].flags)) == -1)
  866.            error("OUT OF MEM. SAVE YOUR WORK. CRASH IS NEAR.",0);
  867.      setborder(-sprite[foe[path]->sprite].sprite->xs, -sprite[foe[path]->sprite].sprite->ys, 320, YMAX);
  868.      }
  869.      showpath(x, y, path, 11);
  870.      putsprite(tmphandle, x, y, 0);
  871.       }
  872.  
  873.    } while (!b);
  874.    killsprite(tmphandle);
  875.  
  876.    return b;
  877.  
  878. }
  879.  
  880. int getsprite(void)
  881. {
  882.  
  883.    do {
  884.       x0 = x; y0 = y;
  885.       getpos(&b, &x, &y);
  886.       getkey();
  887.       if ((x0 != x) || (y0 != y)) {
  888.      removesprite(handle, x0, y0);
  889.      putsprite(handle, x, y, 0);
  890.       }
  891.    } while (!b);
  892.  
  893.    return b;
  894.  
  895. }
  896.  
  897.  
  898.  
  899. void copytoindex(void)
  900. {
  901.    int  i;
  902.  
  903.    for (i = 0; i < nfoes; i++)
  904.       ptrindex[i] = foe[i];
  905. }
  906.  
  907.  
  908. void doinsertion(void)
  909. {
  910.    int   i, n;
  911.  
  912.    if (sfoe == -1) return;
  913.    writetext(0, STATLINE-8, "1.RELE,2.MARK,3.SWITCH,4.SND,5.WAIT", font);
  914.  
  915.    switch (getch()) {
  916.  
  917.       case '1': // Release sprite.
  918.      if (nfoes <= 1) break;
  919.      if (path == sfoe)
  920.         if (sfoe == 0) path = 1; else path = 0;
  921.      pathedit = 0;
  922.      removesprite(handle, x, y);
  923.      b = getpath();
  924.      pathedit = 1;
  925.      if (b == 1) { // Left mouse pressed
  926.         insertcommand(findcommand(NULL, runpos, 1), 4,
  927.               FOERELEASEFOE, path, x-runx, y-runy);
  928.      }
  929.       break;
  930.  
  931.       case '2': // Cycle MARK
  932.      insertcommand(findcommand(NULL, runpos, 1), 1, FOEMARK);
  933.      break;
  934.  
  935.       case '3': // Switch CYCLEPATH <-> ENDPATH
  936.      if ((unsigned)tmp[runpos] == FOECYCLEPATH)
  937.         tmp[runpos] = FOEENDPATH;
  938.      else if ((unsigned)tmp[runpos] == FOEENDPATH)
  939.         tmp[runpos] = FOECYCLEPATH;
  940.      foe[sfoe]->path[runpos] = tmp[runpos];
  941.       break;
  942.  
  943.       case '4': // Sound a bit around.
  944.      insertcommand(findcommand(NULL, runpos, 1), 2,
  945.                FOESOUND, getdec("SND."));
  946.       break;
  947.  
  948.       case '5': // Wait at position.
  949.      n = getdec("WAITS (22 IS 1 SEC).");
  950.      for (i = 0; i < n; i++)
  951.         insertcommand(findcommand(NULL, runpos, 1), 2, 0, 0);
  952.       break;
  953.  
  954.    }
  955.  
  956. }
  957.  
  958. void doattackinsert(void)
  959. {
  960.    writetext(0, STATLINE-8, "1.GO,2.STOP,3.SND,4.MARK", font);
  961.  
  962.    switch (getch()) {
  963.  
  964.       case '1': // Go starfield, go.
  965.      sattack = nattacks++;
  966.      attack[sattack].count = count;
  967.      attack[sattack].foe = A_GOFIELD;
  968.       break;
  969.  
  970.       case '2': // Stop Starfield.
  971.      sattack = nattacks++;
  972.      attack[sattack].count = count;
  973.      attack[sattack].foe = A_STOPFIELD;
  974.       break;
  975.  
  976.       case '3': // Sound a bit around.
  977.      sattack = nattacks++;
  978.      attack[sattack].count = count;
  979.      attack[sattack].foe = A_SOUND;
  980.      attack[sattack].x = getdec("SND.");
  981.       break;
  982.  
  983.       case '4': // Mark position.
  984.      sattack = nattacks++;
  985.      attack[sattack].count = count;
  986.      attack[sattack].foe = A_MARK;
  987.       break;
  988.  
  989.    }
  990.  
  991. }
  992.  
  993.  
  994. void copypath(void)
  995. {
  996.  
  997.    if (sfoe != -1) killsprite(handle2); else return;
  998.    if ((foe[nfoes] = malloc(pathlen[sfoe])) != NULL) {
  999.       xstart[nfoes] = xstart[sfoe];
  1000.       ystart[nfoes] = ystart[sfoe];
  1001.       pathlen[nfoes] = pathlen[sfoe];
  1002.       memcpy(foe[nfoes], foe[sfoe], pathlen[sfoe]);
  1003.       foe[nfoes]->sprite = sspr;
  1004.       handle2 = defsprite(sprite[sspr].sprite, sprite[sspr].flags);
  1005.       sfoe = nfoes++;
  1006.    } else
  1007.       error("OUT OF MEMORY IN STOREPATH", 0);
  1008.  
  1009. }
  1010.  
  1011.  
  1012. int getkey(void)
  1013. {
  1014.    int   ch1, ch2;
  1015.    int   i;
  1016.  
  1017.  
  1018.    ch1 = ch2 = 0xff;
  1019.    if(kbhit()) ch1 = getch();
  1020.    if(ch1 == 0) ch2 = getch();
  1021.  
  1022.    if (ch1 != 0xff)
  1023.    if (ch1 == 0) {
  1024.  
  1025.       switch (ch2) {
  1026.  
  1027.  
  1028.      case 'A':
  1029.      case 'B': if (pathedit) {
  1030.               if (sfoe != -1) {
  1031.              sfoe = roll(sfoe, 0, nfoes - 1, ch2 - 'A');
  1032.              newfoe();
  1033.               }
  1034.            } else if (attackedit) {
  1035.               path = roll(path, 0, nfoes - 1, ch2 - 'A');
  1036.            } else {
  1037.               do {
  1038.              path = roll(path, 0, nfoes - 1, ch2 - 'A');
  1039.               } while (path == sfoe);
  1040.            }
  1041.            break;
  1042.  
  1043.      case 'C': // F9
  1044.      case 'D': if (attackedit) break;
  1045.            removesprite(handle, x, y);  // F10
  1046.            setpos(x+xa, y+ya);
  1047.            getpos(&b, &x, &y);
  1048.            sspr = roll(sspr, 0, nsprites - 1, ch2 - 'C');
  1049.            newsprite();
  1050.            break;
  1051.  
  1052.      case 'S': // Del key
  1053.            if (pathedit) deletecommand(runpos);
  1054.            break;
  1055.  
  1056.      case 'R': // Insert key
  1057.            if (pathedit) {
  1058.               doinsertion();
  1059.               removesprite(handle, x, y);  // F10
  1060.               setpos(x+xa, y+ya);
  1061.               getpos(&b, &x, &y);
  1062.               newsprite();
  1063.            } else {
  1064.               doattackinsert();
  1065.               sort();
  1066.            }
  1067.            break;
  1068.  
  1069.  
  1070.      default:  if (attackedit) animateabit(ch2);
  1071.            if (pathedit) doonestep(ch2);
  1072.            break;
  1073.       }
  1074.  
  1075.       status();
  1076.  
  1077.    } else {
  1078.  
  1079.       switch (ch1) {
  1080.  
  1081.      case '-': if (attackedit) break;
  1082.            speed -= 1;
  1083.            if (speed == 0) speed = 1;
  1084.            break;
  1085.      case '=':
  1086.      case '+': if (attackedit) break;
  1087.            speed += 1;
  1088.            if (speed == 16) speed = 15;
  1089.            break;
  1090.  
  1091.      case 'e': if (!pathedit) break;
  1092.            killsprite(handle);
  1093.            shutxmode();
  1094.            editvalues();
  1095.            initxmode();
  1096.            setborder(-sprite[sspr].sprite->xs, -sprite[sspr].sprite->ys, 320, YMAX);
  1097.            handle = defsprite(sprite[sspr].sprite, sprite[sspr].flags);
  1098.            newfoe();
  1099.            putsprite(handle, x, y, 0);
  1100.            break;
  1101.  
  1102.      case 'd': if (pathedit) {
  1103.               delpath();  // Delete.
  1104.               newfoe();
  1105.               putsprite(handle, x, y, 0);
  1106.               writetext(0, 50, "PLEASE REMEMBER, THAT FOE REFERENCES", font);
  1107.               writetext(0, 58, "IN EXPLOSIONS ARE NOT ADJUSTED.", font);
  1108.            } else if (attackedit) {
  1109.               delattack();
  1110.               sort();
  1111.            }
  1112.            break;
  1113.  
  1114.      case 'c': if (attackedit) {
  1115.               clearscreen();
  1116.               for (i = 0; i < MAXANI; i++) {
  1117.              if (animate[i].foe != -1)
  1118.                 putsprite(animate[i].sprite,
  1119.                       animate[i].x, animate[i].y, 0);
  1120.               }
  1121.            } else if (pathedit) {
  1122.               clearscreen();
  1123.            }
  1124.            break;
  1125.  
  1126.      case 's': // Ein Schuss definieren.
  1127.            if (!pathedit) break;
  1128.            if (sfoe != -1) killsprite(handle2);
  1129.            sfoe = -1; lastkey = 'M';
  1130.            tmpfoe.flags = FOE_LINE;
  1131.            tmpfoe.speed = speed;
  1132.            runx = tmpxstart = XMAX/2;
  1133.            runy = tmpystart = YMAX/2;
  1134.            tmppos = 0;
  1135.            tmpfoe.sprite = sspr;
  1136.            runpos = -1;
  1137.            tmp[tmppos++] = FOEENDPATH;
  1138.            storepath();
  1139.            newfoe();
  1140.            break;
  1141.  
  1142.      case 'o': // Copy path.
  1143.            if (!pathedit) break;
  1144.            copypath();
  1145.            break;
  1146.  
  1147.      case 'q': return TRUE;
  1148.  
  1149.      default:  if (attackedit) animateabit(ch1);
  1150.            if (pathedit) doonestep(ch1);
  1151.            break;
  1152.  
  1153.       }
  1154.  
  1155.       status();
  1156.  
  1157.    }
  1158.  
  1159.    return FALSE;
  1160.  
  1161. }
  1162.  
  1163.  
  1164. int getline(int *x1, int *y1, int *x2, int *y2)
  1165. {
  1166.  
  1167.    *x1 = x + xa; *y1 = y + ya;
  1168.  
  1169.    waitforrelease(&x, &y);
  1170.    xorline(*x1, *y1, x0 = x+xa, y0 = y+ya, 15);
  1171.  
  1172.    do {
  1173.       do {
  1174.     getpos(&b, &x, &y);
  1175.     getkey();
  1176.       } while (!b && (x == x0-xa) && (y == y0-ya));
  1177.  
  1178.       xorline(*x1, *y1, x0, y0, 15);
  1179.       xorline(*x1, *y1, x+xa, y+ya, 15);
  1180.       x0 = x+xa; y0 = y+ya;
  1181.  
  1182.    } while (!b);
  1183.  
  1184.    *x1 -= xa; *y1 -= ya;
  1185.    *x2 = x; *y2 = y;
  1186.    return b;
  1187.  
  1188. }
  1189.  
  1190.  
  1191.  
  1192. int addpath(void)
  1193. {
  1194.    int   x1, y1, x2, y2;
  1195.    int   flag;
  1196.    int   cspr;
  1197.  
  1198.  
  1199.    if (nfoes < 400) {
  1200.  
  1201.       if (sfoe != -1) killsprite(handle2);
  1202.       sfoe = -1; lastkey = 'M';
  1203.       tmpfoe.flags = FOE_PATH;
  1204.       tmpfoe.speed = speed;
  1205.  
  1206.       tmppos = 0;
  1207.       tmpfoe.sprite = sspr;
  1208.       runpos = -1;
  1209.       cspr = sspr;
  1210.       pixelcount = 0;
  1211.  
  1212.       removesprite(handle, x, y);
  1213.       x &= (sprite[sspr].flags == 4 ? 0xfffc : 0xfffe);
  1214.       runx = tmpxstart = x;
  1215.       runy = tmpystart = y;
  1216.       putsprite(handle, x, y, 0);
  1217.  
  1218.       if ((flag = getline(&x1, &y1, &x2, &y2)) != 2) {
  1219.      if (cspr != sspr) {
  1220.         tmp[tmppos++] = FOECHANGESPRITE;
  1221.         tmp[tmppos++] = sspr;
  1222.         cspr = sspr;
  1223.      }
  1224.      tmpline(x1, y1, x2, y2, speed, 1);
  1225.      flag = getline(&x1, &y1, &x2, &y2);
  1226.  
  1227.      while (flag != 2) {
  1228.         if (cspr != sspr) {
  1229.            tmp[tmppos++] = FOECHANGESPRITE;
  1230.            tmp[tmppos++] = sspr;
  1231.            cspr = sspr;
  1232.         }
  1233.         tmpline(x1, y1, x2, y2, speed, 0);
  1234.         flag = getline(&x1, &y1, &x2, &y2);
  1235.      }
  1236.  
  1237.      tmp[tmppos++] = FOEENDPATH;
  1238.       }
  1239.       putsprite(handle, x, y, 0);
  1240.       runx = tmpxstart; runy = tmpystart;
  1241.       return 0;
  1242.    } else {
  1243.       error("FOE INDEX FULL.",0);
  1244.       return -1;
  1245.    }
  1246. }
  1247.  
  1248.  
  1249.  
  1250.  
  1251. int newpath(void)
  1252. {
  1253.  
  1254.  
  1255.    if (sprite == NULL) {
  1256.       printf("\nSprite Library not loaded.\n");
  1257.       return -1;
  1258.    }
  1259.  
  1260.  
  1261.    initxmode();
  1262.    initmouse();
  1263.  
  1264.    handle = defsprite(sprite[sspr].sprite, sprite[sspr].flags);
  1265.    setborder(-sprite[sspr].sprite->xs, -sprite[sspr].sprite->ys, 320, YMAX);
  1266.    xa = sprite[sspr].sprite->xs/2; ya = sprite[sspr].sprite->ys/2;
  1267.  
  1268.    status();
  1269.    getpos(&b, &x, &y);
  1270.  
  1271.    if (sfoe != -1)
  1272.       handle2 = defsprite(sprite[0].sprite,4); // Just define ANY sprite.
  1273.    newfoe();
  1274.  
  1275.    do {
  1276.       x0 = x; y0 = y;
  1277.       getpos(&b, &x, &y);
  1278.       if (b == 1) {
  1279.      if (addpath() == 0) {
  1280.         storepath();
  1281.         newfoe();
  1282.      }
  1283.      status();
  1284.       }
  1285.       if ((x0 != x) || (y0 != y)) {
  1286.      removesprite(handle, x0, y0);
  1287.      putsprite(handle, x, y, 0);
  1288.       }
  1289.  
  1290.  
  1291.    } while (!getkey());
  1292.  
  1293.    killallsprites();
  1294.  
  1295.    clearmouse();
  1296.    shutxmode();
  1297.  
  1298.    return 0;
  1299. }
  1300.  
  1301.  
  1302.  
  1303. void editattack(void)
  1304. {
  1305.  
  1306.    if (sprite == NULL) {
  1307.       printf("\nSprite library not loaded.\n\n");
  1308.       return;
  1309.    }
  1310.    if (nfoes == 0) {
  1311.       printf("\nNot even a single enemy defined. Can't continue.\n\n");
  1312.       return;
  1313.    }
  1314.  
  1315.    initxmode();
  1316.    initmouse();
  1317.  
  1318.    initanimate();
  1319.    lastkey = 'M';
  1320.    path = 0;
  1321.    getpos(&b, &x, &y);
  1322.  
  1323.    status();
  1324.    do {
  1325.       b = getpath();
  1326.       if (b == 1) {
  1327.      sattack = nattacks++;
  1328.      attack[sattack].count = count;
  1329.      attack[sattack].x = x; attack[sattack].y = y;
  1330.      attack[sattack].foe = path;
  1331.      showpath(x, y, path, 12);
  1332.      sort();
  1333.      delay(200);
  1334.       }
  1335.    } while (b != -1);
  1336.  
  1337.    killallsprites();
  1338.  
  1339.    clearmouse();
  1340.    shutxmode();
  1341.  
  1342. }
  1343.  
  1344.  
  1345. int loadfont(void)
  1346. {
  1347.    int      filvar;
  1348.    long        size;
  1349.    int      nentries;
  1350.    int      i;
  1351.  
  1352.    if ((filvar = open("font1.spr", O_RDONLY | O_BINARY, S_IREAD)) == -1) {
  1353.       return -1;
  1354.    }
  1355.    size = filelength(filvar);
  1356.  
  1357.    if ((font = malloc(size)) == NULL) {
  1358.       close(filvar);
  1359.       return -1;
  1360.    }
  1361.    read(filvar, font, size);
  1362.    close(filvar);
  1363.  
  1364.    return 0;
  1365.  
  1366. }
  1367.  
  1368.  
  1369.  
  1370. int loadpathes(char *file)
  1371. {
  1372.    char     fname[80];
  1373.    int      filvar, filvar1;
  1374.    int      nentries;
  1375.    int      i;
  1376.  
  1377.    strcpy(fname, file);
  1378.    if ((filvar = open(strcat(fname, ".FOE"), O_RDONLY | O_BINARY, S_IREAD)) == -1) {
  1379.       return -1;
  1380.    }
  1381.    read(filvar, &nfoes, sizeof(nfoes));
  1382.  
  1383. // Read start points
  1384.    strcpy(fname, file);
  1385.    if ((filvar1 = open(strcat(fname, ".FSP"), O_RDONLY | O_BINARY, S_IREAD)) == -1) {
  1386.       return -1;
  1387.    }
  1388.    read(filvar1, xstart, nfoes*2);
  1389.    read(filvar1, ystart, nfoes*2);
  1390.    read(filvar1, pathlen, nfoes*2);
  1391.    close(filvar1);
  1392. // --
  1393.  
  1394.    read(filvar, foe, nfoes*4);
  1395.  
  1396.    for (i = 0; i < nfoes; i++) {
  1397.       if ((foe[i] = malloc(pathlen[i])) == NULL) {
  1398.      close(filvar);
  1399.      return -1;
  1400.       }
  1401.       read(filvar, foe[i], pathlen[i]);
  1402.    }
  1403.    close(filvar);
  1404.  
  1405.    strcpy(fname, file);
  1406.    if ((filvar = open(strcat(fname, ".TBL"), O_RDONLY | O_BINARY, S_IREAD)) == -1) {
  1407.       return -1;
  1408.    }
  1409.    read(filvar, &nattacks, sizeof(nattacks));
  1410.    read(filvar, attack, nattacks * sizeof(struct attackstrc));
  1411.    close(filvar);
  1412.  
  1413.    return 0;
  1414. }
  1415.  
  1416.  
  1417.  
  1418. int savepathes(char *file)
  1419. {
  1420.    char      fname[80];
  1421.    int       filvar, i;
  1422.    long      ptr, ptr0;
  1423.    long      fptr1, fptr2;
  1424.    unsigned  size;
  1425.  
  1426.  
  1427.    strcpy(fname, file);
  1428.    filvar = open(strcat(fname, ".FOE"), O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, S_IWRITE);
  1429.    if (filvar == -1) return -1;
  1430.  
  1431.    write(filvar, &nfoes, 2);
  1432.    fptr1 = tell(filvar);
  1433.    ptr = nfoes*4;
  1434.    write(filvar, foe, ptr);
  1435.  
  1436.    for (i = 0; i < nfoes; i++) {
  1437.       write(filvar, foe[i], pathlen[i]);
  1438.       fptr2 = tell(filvar);
  1439.       lseek(filvar, fptr1, SEEK_SET);
  1440.       ptr0 = (ptr & 0xf) + ((ptr & 0xffff0) << 12);
  1441.       write(filvar, &ptr0, 4);
  1442.       ptr += pathlen[i];
  1443.       fptr1 = tell(filvar);
  1444.       lseek(filvar, fptr2, SEEK_SET);
  1445.  
  1446.    }
  1447.    close(filvar);
  1448.  
  1449.    strcpy(fname, file);
  1450.    filvar = open(strcat(fname, ".FSP"), O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, S_IWRITE);
  1451.    if (filvar == -1) return -1;
  1452.    write(filvar, xstart, nfoes*2); write(filvar, ystart, nfoes*2);
  1453.    write(filvar, pathlen, nfoes*2);
  1454.    close(filvar);
  1455.  
  1456.    strcpy(fname, file);
  1457.    filvar = open(strcat(fname, ".TBL"), O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, S_IWRITE);
  1458.    if (filvar == -1) return -1;
  1459.    write(filvar, &nattacks, 2);
  1460.    write(filvar, attack, nattacks*sizeof(struct attackstrc));
  1461.    close(filvar);
  1462.  
  1463.    return 0;
  1464.  
  1465. }
  1466.  
  1467.  
  1468. int readslib(char *file)
  1469. {
  1470.    int      filvar;
  1471.    long        size;
  1472.    int      nentries;
  1473.    int      i;
  1474.    char     huge *h;
  1475.  
  1476.    if ((filvar = open(file, O_RDONLY | O_BINARY, S_IREAD)) == -1) {
  1477.       return -1;
  1478.    }
  1479.    read(filvar, &nsprites, sizeof(nsprites));
  1480.    size = filelength(filvar) - sizeof(nsprites);
  1481.  
  1482.    if ((sprite = farmalloc(size)) == NULL) {
  1483.       close(filvar);
  1484.       return -1;
  1485.    }
  1486.    h = (char *)sprite;
  1487.    while (size > 65000) {
  1488.       read(filvar, h, 65000);
  1489.       h += 65000; size -= 65000;
  1490.    }
  1491.    read(filvar, h, size);
  1492.    close(filvar);
  1493.  
  1494.  
  1495. // Relocate pointers to single data elements.
  1496.    for (i = 0; i < nsprites; i++) {
  1497.       (long)sprite[i].sprite += (long)sprite;
  1498.    }
  1499.  
  1500.    return 0;
  1501. }
  1502.  
  1503.  
  1504. void shutsprites(void)
  1505. {
  1506.    if (sprite != NULL) farfree(sprite);
  1507. }
  1508.  
  1509.  
  1510. int main(void)
  1511. {
  1512.    char   libfile[80];
  1513.    int    choice;
  1514.    int    i;
  1515.  
  1516.    screenmode(0x02);
  1517.  
  1518.    printf("\n\nBaller Game PATH EDITOR "
  1519.       "[c] copyright by ALPHA-HELIX Dec 92.\n\n");
  1520.  
  1521.    if (loadfont() == -1) {
  1522.       printf("Font file not found !\n");
  1523.       abort();
  1524.    }
  1525.  
  1526.    tmpfoe.score = 33; tmpfoe.shield = 1; tmpfoe.expl = 0;
  1527.  
  1528.    do {
  1529.  
  1530.    do {
  1531.       printf("\n\n");
  1532.       printf("1 - Edit Pathes.\n");
  1533.       printf("2 - Edit Attack Table.\n");
  1534.       printf("6 - Load Pathes.\n");
  1535.       printf("7 - Save Pathes.\n");
  1536.       printf("8 - Read Sprite Library.\n");
  1537.       printf("9 - Quit PE.\n");
  1538.  
  1539.       printf("\nYour choice -> "); choice = getche() - '0';
  1540.       printf("\n\n");
  1541.  
  1542.       switch (choice) {
  1543.      case 1: pathedit = 1;
  1544.          newpath();
  1545.          pathedit = 0;
  1546.          break;
  1547.  
  1548.      case 2: attackedit = 1;
  1549.          editattack();
  1550.          attackedit = 0;
  1551.          break;
  1552.  
  1553.      case 6: printf("Foe File [.FOE]: ");
  1554.          fflush(stdin);
  1555.          scanf("%s", libfile);
  1556.          for (i = 0; i < nfoes; i++)
  1557.             free(foe[i]);
  1558.          if (loadpathes(libfile) == -1) {
  1559.             perror("File not read: ");
  1560.          } else {
  1561.             sfoe = 0;
  1562.          }
  1563.          break;
  1564.  
  1565.      case 7: printf("Foe File [.FOE]: ");
  1566.          fflush(stdin);
  1567.          scanf("%s", libfile);
  1568.          sort();
  1569.          if (savepathes(libfile) == -1) {
  1570.             perror("File not written: ");
  1571.          }
  1572.          break;
  1573.  
  1574.      case 8: printf("Sprite Library [.SLI]: ");
  1575.          fflush(stdin);
  1576.          scanf("%s", libfile);
  1577.          strcat(libfile, ".SLI");
  1578.          shutsprites();
  1579.          readslib(libfile);
  1580.          sspr = 0;
  1581.          break;
  1582.  
  1583.  
  1584.       }
  1585.  
  1586.    } while (choice != 9);
  1587.  
  1588.    printf("\n\nQuit without saving (Y/N)? "); choice = getche();
  1589.    } while (choice != 'y');
  1590.  
  1591.    for (i = 0; i < nfoes; i++)
  1592.       free(foe[i]);
  1593.    shutsprites();
  1594.    free(font);
  1595.    printf("\nThanks for using PE !\n\n\n\n");
  1596.  
  1597.    return 0;
  1598. }